/*
 * Quercia Luciano
 * Algoritmi e Strutture Dati
 * a.a. 2009-10
 */


#ifndef _CODA_H_
#define _CODA_H_


#include <iostream>
using namespace std;

#define NDEBUG
#include <cassert>



#include "nodoQ.h"

template <class T>
class Coda {
public:
	Coda();
	~Coda();

	//operatori
	bool codaVuota();

	void fuoriCoda()         throw (char const *);
	void inCoda(T elem);
	T leggiCoda()               throw (char const *);


	//funzioni di servizio
	void print(void);
	void printAll(void);

private:
	typedef NodoQ<T> * posizione;

	int nNodi;
	posizione top;
	posizione bottom;
};




/*****************************
 *        DEFINIZIONI        *
 *     dei metodi di Coda    *
 *****************************/


template <class T>
Coda<T>::Coda() {
	top = NULL ;
	bottom = NULL ;
	nNodi = 0 ;
}



template <class T>
Coda<T>::~Coda() {
	while ( !codaVuota() )
		fuoriCoda();
}



template <class T>
bool Coda<T>::codaVuota() {
	if ( nNodi == 0 )
		return true;
	else
		return false;
}



template <class T>
void Coda<T>::inCoda(T elem) {
	NodoQ<T> *temp = new NodoQ<T>;

	temp->setValue( elem ) ;
	if (top == NULL)
		top = temp;
	if (bottom != NULL)
		bottom->setLink(temp) ;
	bottom = temp ;
	nNodi++ ;
}


template <class T>
void Coda<T>::fuoriCoda() throw (char const *) {
	if ( !codaVuota() ) {
		NodoQ<T> *temp= new NodoQ<T> ;
		temp = top ;
		top = top->getLink() ;
		delete temp ;
		nNodi-- ;
	} else
		throw "Impossibile cancellare da una Coda vuota." ;
}



template <class T>
T Coda<T>::leggiCoda() throw (char const *) {
	if ( !codaVuota() )
		return top->getValue() ;
	else
		throw "Impossibile leggere il Nodo da una Coda Vuota." ;
}



template <class T>
void Coda<T>::print(void) {
	if ( ! codaVuota() ) {
		cout << "[ " << leggiCoda() << " ]" << endl ;
	} else
		cout << "[ Empty Queue ]" << endl ;
}


template <class T>
void Coda<T>::printAll(void) {
	if ( ! codaVuota() ) {
		cout << "[ " ;

		posizione p;
		p = top;
		for (int i = 0; i<nNodi; i++) {
			cout << p->getValue() << " " ;
			p = p->getLink();
		}

		cout << "]" << endl ;
	} else
		cout << "[ Empty Queue ]" << endl ;
}

#endif
